#!/bin/python3
import os
import platform
import random
import socket
import subprocess
import sys
import time
import traceback
from urllib import parse
try:
    print('本配置程序依赖 tkinter (python3-tk)')
    from tkinter import *
    from tkinter import scrolledtext
    import tkinter.messagebox as mbox
    import tkinter.filedialog as fdialog
except:
    os.system('notify-send "检测到缺少依赖 python3-tk 尝试安装...需要 sudo 权限，请在终端中执行以便输入密码"')
    print('检测到缺少依赖 python3-tk 尝试安装...')
    os.system('sudo apt -y install python3-tk')
    from tkinter import *
    from tkinter import scrolledtext
    import tkinter.messagebox as mbox
    import tkinter.filedialog as fdialog
try:
    print('本配置程序依赖 python3-pil python3-pil.imagetk')
    from PIL import Image, ImageTk
except:
    os.system('notify-send "检测到缺少依赖 python3-pil python3-pil.imagetk 尝试安装...需要 sudo 权限，请在终端中执行以便输入密码"')
    print('检测到缺少依赖 python3-pil python3-pil.imagetk 尝试安装...')
    os.system('sudo apt install -y python3-pil python3-pil.imagetk')
    from PIL import Image, ImageTk


HOME_FOLDER = ''
WALLPAPGER_FOLER = '/.ckp_wallpaper/wallpaper_folder.conf'
WALLPAPGER_SLEEP = '/.ckp_wallpaper/wallpaper_sleep.conf'
AUTOSTART_DESKTOP = '/.config/autostart/ckp_wallpaper.desktop'
MAIN_SHELL = '/.ckp_wallpaper/ckp_wallpaper.py'


def base_folder():
    return HOME_FOLDER + '/.ckp_wallpaper'


def now():
    return time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())


def print_short_line(l=20):
    print('-'*l)


def exec_shell(cmd):
    '''
    执行 shell 返回 exitstatus
    '''
    exitstatus, output = subprocess.getstatusoutput(cmd)
    return exitstatus, output


def trim_line(s):
    return s.replace('\n', '').replace('\r', '')


def read_file(fileFullPath):
    try:
        if not os.path.exists(base_folder()):
            os.makedirs(base_folder())
        f = open(fileFullPath, 'r')
        contxtlist = f.readlines()
        f.close()
        content = ''.join(contxtlist)
        return content
    except FileNotFoundError as err:
        return 'FileNotFound'
    else:
        return 'IOError'


def write_file(fileFullPath, content):
    try:
        if not os.path.exists(base_folder()):
            os.makedirs(base_folder())
        with open(fileFullPath, 'w') as f:
            f.write(content)
        return 'success'
    except FileNotFoundError as err:
        return 'FileNotFound: ' + fileFullPath
    else:
        return 'IOError: ' + fileFullPath


def delete_file(fileFullPath):
    try:
        os.remove(fileFullPath)
        return 'success'
    except Exception as err:
        return 'IOError：' + fileFullPath


def get_wallpaper_folder():
    folder = read_file(HOME_FOLDER + WALLPAPGER_FOLER)
    if folder == '' or folder == 'FileNotFound' or folder == 'IOError':
        folder = HOME_FOLDER + '/Pictures'
    return trim_line(folder)


def set_wallpaper_folder():
    folder = trim_line(folder_Text.get(1.0, END))
    folder = folder.replace('file://', '')
    result = write_file(HOME_FOLDER + WALLPAPGER_FOLER, folder)
    mbox.showinfo('提示', '保存目录设置：' + result)
    folder_Text.delete(1.0, END)
    folder_Text.insert(1.0, get_wallpaper_folder())


def get_autostart():
    result = read_file(HOME_FOLDER + AUTOSTART_DESKTOP)
    if result == 'FileNotFound' or result == 'IOError':
        result = ''
    return result


def set_autostart():
    desktop = '''[Desktop Entry]
Comment=设置屏幕壁纸
Exec={home}{MAIN_SHELL}
Hidden=false
Icon=deepin-image-viewer
Name=屏幕壁纸
Terminal=false
Type=Application
Version=1.0'''
    result = write_file(HOME_FOLDER + AUTOSTART_DESKTOP, desktop.replace('{home}', HOME_FOLDER).replace('{MAIN_SHELL}', MAIN_SHELL))
    mbox.showinfo('提示', '创建/覆盖自启动文件：' + result)
    autostart_Text.config(state=NORMAL)
    autostart_Text.delete(1.0, END)
    autostart_Text.insert(1.0, get_autostart())
    autostart_Text.config(state=DISABLED)


def set_autostart_remove():
    result = delete_file(HOME_FOLDER + AUTOSTART_DESKTOP)
    mbox.showinfo('提示', '移除自启动文件：' + result)
    autostart_Text.config(state=NORMAL)
    autostart_Text.delete(1.0, END)
    autostart_Text.insert(1.0, '')
    autostart_Text.config(state=DISABLED)


def set_autostart_stop():
    print(exec_shell('ps aux|grep "%s" |grep -v grep | awk \'{print $2}\' | xargs kill -9' % MAIN_SHELL))
    mbox.showinfo('提示', '停止壁纸切换脚本进程：已执行完毕')


def set_autostart_start():
    print(exec_shell('nohup %s >/dev/null 2>&1 &' % (HOME_FOLDER + MAIN_SHELL)))
    mbox.showinfo('提示', '启动壁纸切换：已执行完毕')


def get_menu():
    desktop = '''[Desktop Entry]
Type=Application
Exec=python3 {home}{MAIN_SHELL} --action=next
Icon=deepin-image-viewer
Name=下一张壁纸
X-DFM-MenuTypes=EmptyArea;
X-DFM-NotShowIn=FileManager'''
    return desktop.replace('{home}', HOME_FOLDER).replace('{MAIN_SHELL}', MAIN_SHELL)


def open_dedit():
    process = subprocess.Popen(
        ['kate /usr/share/deepin/dde-file-manager/oem-menuextensions/ckp_wallpaper.desktop'], shell=True, close_fds=True)


def menu_set():
    write_file('/tmp/ckp_wallpaper.desktop', get_menu())
    process = subprocess.Popen(
        ['pkexec /bin/env DISPLAY=$DISPLAY XAUTHORITY=$XAUTHORITY mv -f /tmp/ckp_wallpaper.desktop /usr/share/deepin/dde-file-manager/oem-menuextensions/ckp_wallpaper.desktop'],
        stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=True, close_fds=True)
    stdout, stderr = process.communicate()
    result = '失败'
    stdout = stdout.decode()
    if stdout.count('Error') == 0:
        if os.path.isfile('/usr/share/deepin/dde-file-manager/oem-menuextensions/ckp_wallpaper.desktop'):
            result = '成功'
    else:
        result = 'sudo 授权失败'
    if result == '成功':
        mbox.showinfo('提示', '创建桌面右键菜单：' + result)
    else:
        mbox.showwarning('提示', '创建桌面右键菜单：' + result)


def get_sh():
    result = read_file(HOME_FOLDER + MAIN_SHELL)
    return result


def create_sh():
    shell = read_file('{0}/ckp_wallpaper_main.py'.format(os.path.dirname(__file__)))
    sleep_secs = menu_sleep_Text.get(1.0, END).strip()
    shell = shell.replace('{home}', HOME_FOLDER)
    shell = shell.replace('{sleep}', sleep_secs)
    result = write_file(HOME_FOLDER + MAIN_SHELL, shell)
    exec_shell("chmod +x " + HOME_FOLDER + MAIN_SHELL)
    mbox.showinfo('提示', '创建/覆盖主脚本：' + result)
    shell_Text.config(state=NORMAL)
    shell_Text.delete(1.0, END)
    shell_Text.insert(1.0, get_sh())
    shell_Text.config(state=DISABLED)
    result = write_file(HOME_FOLDER + WALLPAPGER_SLEEP, sleep_secs)


def ask_dir():
    # print(folder_Text.get(1.0, END))
    # print_short_line()
    f = fdialog.askdirectory(initialdir=trim_line(folder_Text.get(1.0, END)))
    # mbox.showinfo('提示', '[' + str(len(f)) + ']' + str(type(f)))
    if f == None or len(f) == 0 or f == '':
        mbox.showwarning('提示', '没有选择任何目录')
        return
    else:
        # folder_Text['state'] = 'normal'
        folder_Text.delete(1.0, END)
        folder_Text.insert(1.0, f)
        # folder_Text['state'] = 'readonly'
        set_wallpaper_folder()


def menu_cut(editor, event=None):
    editor.event_generate("<<Cut>>")


def menu_copy(editor, event=None):
    editor.event_generate("<<Copy>>")


def menu_paste(editor, event=None):
    editor.event_generate('<<Paste>>')


def menu_undo(editor, event=None):
    if not isinstance(editor, Text):
        mbox.showwarning('提示', '不支持 撤销/undo 操作')
        return
    editor.event_generate('<<Undo>>')
    # editor.edit_undo()


def menu_redo(editor, event=None):
    if not isinstance(editor, Text):
        mbox.showwarning('提示', '不支持 恢复/redo 操作')
        return
    editor.event_generate('<<Redo>>')
    # editor.edit_redo()


def menu_select_all(editor, event=None):
    editor.event_generate('<<SelectAll>>')


def menu_rightKey(event, editor):
    menubar.delete(0, END)
    menubar.add_command(label='剪切', accelerator='Ctrl+X', command=lambda: menu_cut(editor))
    menubar.add_command(label='复制', accelerator='Ctrl+C', command=lambda: menu_copy(editor))
    menubar.add_command(label='粘贴', accelerator='Ctrl+V', command=lambda: menu_paste(editor))
    menubar.add_separator()
    menubar.add_command(label='撤销', accelerator='Ctrl+Z', command=lambda: menu_undo(editor))
    menubar.add_command(label='重做', accelerator='Ctrl+Y', command=lambda: menu_redo(editor))
    menubar.add_separator()
    menubar.add_command(label='全选', accelerator='Ctrl+A', command=lambda: menu_select_all(editor))
    menubar.post(event.x_root, event.y_root)


def on_closing():
    if mbox.askokcancel("提示", top.title() + "\n\n确定要退出吗？"):
        top.destroy()


def load_img(dir):
    for it in os.listdir(dir):
        if not os.path.isfile(it):
            continue
        f_ext = os.path.splitext(it)
        if f_ext == '.jpg' or f_ext == '.png':
            return it


if __name__ == '__main__':
    top_path = os.path.dirname(__file__)
    status, HOME_FOLDER = exec_shell('cd ~/; pwd')
    top = Tk()
    icon_file = top_path + '/logo.png'
    # print(icon_file)
    # print(__file__)
    # print(os.path.dirname(__file__))
    # import os
    # os.path.abspath('.')  # 当前所处的文件夹的绝对路径，如/usr/local
    # os.path.abspath('..')  # 当前所处的文件夹上一级文件夹的绝对路径
    # os.path.abspath(os.path.dirname(__file__))  # 当前文件所在绝对路径
    # os.path.abspath(os.path.dirname(os.path.dirname(__file__)))  # 当前文件所在上级绝对路径
    # os.path.abspath(os.path.join(os.getcwd(), ".."))  # 当前文件所在上级绝对路径
    # os.path.abspath(os.path.join(os.getcwd(), "../.."))  # 当前文件所在上上级绝对路径
    try:
        icon = ImageTk.PhotoImage(Image.open(icon_file))
    except Exception as err:
        icon = PhotoImage(height=16, width=16)
        icon.blank()
        print(err)
    top.wm_iconphoto('True', icon)
    # top.resizable(width=False, height=False)
    top.title('Deepin 桌面壁纸自动换')
    width = 1100
    height = 720
    top.geometry('%dx%d+%d+%d' % (width, height, top.winfo_screenwidth()/2-(width/2), top.winfo_screenheight()/2-(height/2)))  # XxY+10+10 定义窗口弹出时的默认展示位置
    # top.attributes("-alpha", 0.2)                           #虚化，值越小虚化程度越高
    # top["bg"] = "lightblue"
    top.protocol("WM_DELETE_WINDOW", on_closing)
    menubar = Menu(top, tearoff=False)  # 创建一个菜单

    # 壁纸目录：
    folder_label = Label(top, text="壁纸目录：")
    folder_label.grid(row=0, column=0, sticky=E)
    # Label(top, text=" "*15).grid(row=0, column=3, sticky=W)

    folder_Text = Text(top, width=100, height=1)  # 原始数据录入框
    folder_Text.grid(row=0, column=1, sticky=W)
    folder_Text.insert(1.0, get_wallpaper_folder())
    # folder_Text['state'] = 'readonly'
    folder_Text.bind("<Button-3>", lambda x: menu_rightKey(x, folder_Text))  # 绑定右键鼠标事件

    folder_sl_btn = Button(top, text='选择...', width=3, command=ask_dir)
    folder_sl_btn.grid(row=0, column=2, sticky=W)

    folder_btn = Button(top, text='1:保存目录设置', width=11, command=set_wallpaper_folder)
    folder_btn.grid(row=0, column=3, sticky=W)
    # 自启动文件：
    autostart_label = Label(top, text="自启动文件：")
    autostart_label.grid(row=1, column=0, sticky=E)

    autostart_Text = Text(top, width=100, height=9, undo=True, maxundo=10)  # 原始数据录入框
    autostart_Text.grid(row=1, column=1, rowspan=9, sticky=W)
    autostart_Text.insert(1.0, get_autostart())
    autostart_Text.config(state=DISABLED)
    autostart_Text.bind("<Button-3>", lambda x: menu_rightKey(x, autostart_Text))  # 绑定右键鼠标事件

    autostart_btn = Button(top, text='2:创建/覆盖自启动文件', width=18, command=set_autostart)
    autostart_btn.grid(row=1, column=2, columnspan=2, sticky=W)

    autostart_rm_btn = Button(top, text='移除自启动文件', width=18, command=set_autostart_remove)
    autostart_rm_btn.grid(row=2, column=2, columnspan=2, sticky=W)

    autostart_stop_btn = Button(top, text='启动壁纸切换', width=18, command=set_autostart_start)
    autostart_stop_btn.grid(row=3, column=2, columnspan=2, sticky=W)

    autostart_stop_btn = Button(top, text='停止壁纸切换', width=18, command=set_autostart_stop)
    autostart_stop_btn.grid(row=4, column=2, columnspan=2, sticky=W)

    autostart_label = Label(top, text="间隔(s)")
    autostart_label.grid(row=18, column=2, columnspan=2, sticky=W)

    sleep_secs_conf = sleep_secs = '120'
    try:
        # print('sleep_secs_conf 1 -> %s' % sleep_secs_conf)
        sleep_secs_conf = read_file(HOME_FOLDER + WALLPAPGER_SLEEP)
        # print('sleep_secs_conf 2 -> %s' % sleep_secs_conf)
        sleep_secs = str(int(sleep_secs_conf))
    except Exception as ex:
        print(ex)
        sleep_secs = '120'
    menu_sleep_Text = Text(top, width=6, height=1, undo=True)
    menu_sleep_Text.grid(row=18, column=3, columnspan=2, sticky=W)
    # print('sleep_secs 2 -> %s' % sleep_secs)
    menu_sleep_Text.insert(1.0, sleep_secs)
    # menu_sleep_Text.config(state=DISABLED)
    menu_sleep_Text.bind("<Button-3>", lambda x: menu_rightKey(x, menu_sleep_Text))

    # 桌面右键文件：
    menu_label = Label(top, text="  桌面右键文件：")
    menu_label.grid(row=10, column=0, sticky=E)

    menu_label_1 = Label(top, bg='lightyellow', text='右键菜单在 /usr/share/deepin/dde-file-manager/oem-menuextensions，需要 sudo 权限，如创建失败请尝试复制下方脚本执行。')
    menu_label_1.grid(row=10, column=1, columnspan=2, sticky=W)

    menu_sh_Text = Text(top, width=100, height=1)  # , height=1
    menu_sh_Text.grid(row=11, column=1, sticky=W)
    menu_sh_Text.insert(1.0, 'sudo deepin-editor /usr/share/deepin/dde-file-manager/oem-menuextensions/ckp_wallpaper.desktop')
    menu_sh_Text.config(state=DISABLED)
    # menu_sh_Text['state'] = 'readonly'
    menu_sh_Text.bind("<Button-3>", lambda x: menu_rightKey(x, menu_sh_Text))  # 绑定右键鼠标事件

    menu_Text = Text(top, width=100, height=7, undo=True)  # 原始数据录入框
    menu_Text.grid(row=12, column=1, rowspan=7, sticky=W)
    menu_Text.insert(1.0, get_menu())
    menu_Text.config(state=DISABLED)
    menu_Text.bind("<Button-3>", lambda x: menu_rightKey(x, menu_Text))  # 绑定右键鼠标事件

    menu_setsh_btn = Button(top, text='3:右键菜单(pkexec)', width=18, command=menu_set)
    menu_setsh_btn.grid(row=11, column=2, columnspan=2, sticky=W)
    # '''
    # menu_sh_btn = Button(top, text='3:右键菜单(需要kate)', width=15, command=open_dedit)
    # menu_sh_btn.grid(row=12, column=3, sticky=W)
    # '''
    # 主脚本：
    shell_label = Label(top, text="主脚本示例：")
    shell_label.grid(row=19, column=0, sticky=E)
    shell_Text = scrolledtext.ScrolledText(top, width=98, height=16, wrap=WORD)  # 原始数据录入框
    shell_Text.grid(row=19, column=1, rowspan=16, sticky=W)
    shell_Text.insert(1.0, get_sh())
    shell_Text.config(state=DISABLED)
    shell_Text.bind("<Button-3>", lambda x: menu_rightKey(x, shell_Text))  # 绑定右键鼠标事件
    # shell_Text.config(yscrollcommand=scroll.set)

    autostart_btn = Button(top, text='4:创建/覆盖主脚本', width=18, command=create_sh)
    autostart_btn.grid(row=19, column=2, columnspan=2, sticky=W)

    Label(top, text="请选择壁纸图片所在目录，仅索引jpg、png图片，文件名带空格会导致该文件无法被设置为壁纸。\n\n上述步骤依次操作，注销重新登录Deepin切换脚本即可自启动。\n\n步骤[3]不是必须，但可以方便手动下一张壁纸；也可以实现立即启动壁纸自动切换。", bg='lightyellow', justify='left', wraplength=170).grid(
        row=20, column=2, columnspan=2, sticky=W)

    # 进入消息循环
    top.mainloop()
